package com.cooper.util;

import java.io.Serializable;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * 
 * @Description: <br>
 * @Date: Jan 15, 2014 9:32:53 PM<br>
 * @Copyright (c) 2014 MiXuan <br> * 
 * @since 1.0
 * @author coral
 */
public class CollectionsNew {
	
	public static <T> void removeDuplicate(List<T> srcList){
		Set<T> set = Sets.newHashSet(srcList);
		srcList.clear();
		srcList.addAll(set);
	}
	
	public static <T> void removeDuplicateWithOrder(List<T> srcList){
		List<T> newList = Lists.newArrayList();
		Set<T> set = Sets.newHashSet();
		for(T obj: srcList){
			if(set.add(obj)){
				newList.add(obj);
			}
		}
		srcList.clear();
		srcList.addAll(newList);
	}
	
	public static <K, T> LinkedHashMap<K, T> makeLinkedHashMap(List<K> keyList, List<T> valueList){
		LinkedHashMap<K, T> retMap = Maps.newLinkedHashMap();
		int valueSize = valueList.size();
		for(int index=0; index < keyList.size(); index++){
			K key = keyList.get(index);
			if(index < valueSize){
				retMap.put(key, valueList.get(index));
			} else {
				break;
			}
		}
		return retMap;
	}
	
	public static <K, T, E> LinkedHashMap<K, T> makeLinkedHashMap(List<E> dataList,
			Function<E, K> keyFunction, Function<E, T> valueFunction){
		LinkedHashMap<K, T> retMap = Maps.newLinkedHashMap();
		if(null == dataList){
			return retMap;
		}
		for(E input: dataList){
			retMap.put(keyFunction.apply(input), valueFunction.apply(input));
		}
		return retMap;
	}
	
	public static <T> List<T> splitToList(String text, Function<String, T> function){
		List<T> retList = new ArrayList<T>();
		List<String> strValueList = Splitter.on(",").splitToList(text);
		for(String strValue: strValueList){
			retList.add(function.apply(strValue));
		}
		return retList;
	}
	
	/**
	 * 添加value到dataMap中, 如果dataMap中没有key，则创建一个。若有，则追加到key值对应的List中
	 * @param dataMap
	 * @param key
	 * @param value
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void appendListValueIntoMap(Map dataMap, Serializable key, Object value){
		List dataList = null;
		if(dataMap.containsKey(key)){
			dataList = (List)dataMap.get(key);
		} else {
			dataList = new ArrayList();
		}
		dataList.add(value);
		dataMap.put(key, dataList);
	}
	
	public static <F, T> Map<F, List<T>> transformToMap(List<T> fromCollection, Function<? super T, F> function){
		return new TransformedMap<F, T>(fromCollection, function);
	}
	
	static class TransformedMap<F, T> extends AbstractMap<F, List<T>> {
	    final Collection<T> fromCollection;
	    final Function<? super T, ? extends F> function;
	    private Map<F, List<T>> dataMap = new HashMap<F, List<T>>();

	    TransformedMap(Collection<T> fromCollection,
	        Function<? super T, ? extends F> function) {
	      this.fromCollection = Preconditions.checkNotNull(fromCollection);
	      this.function = Preconditions.checkNotNull(function);
	      init();
	    }
	    
	    private void init(){
	    	List<T> subList = null;
	    	for(Iterator<T> iter = this.fromCollection.iterator(); iter.hasNext();){
	    		T value = iter.next();
	    		F key = this.function.apply(value);
	    		if(dataMap.containsKey(key)){
	    			subList = dataMap.get(key);
	    		} else {
	    			subList = new ArrayList<T>();
	    		}
	    		subList.add(value);
	    		dataMap.put(key, subList);
	    	}
	    }
	    
	    @Override public void clear() {
	    	dataMap.clear();
	    }

	    @Override public boolean isEmpty() {
	      return dataMap.isEmpty();
	    }

	    @Override public Set<java.util.Map.Entry<F, List<T>>> entrySet() {
			return dataMap.entrySet();
		}
	    
	    @Override
		public boolean containsKey(Object key) {
			return dataMap.containsKey(key);
		}
	    
	    @Override public Set<F> keySet(){
	    	return this.dataMap.keySet();
	    }
	    
	    @Override public List<T> get(Object key){
	    	return this.dataMap.get(key);
	    }
	    
		@Override public int size() {
	      return dataMap.size();
	    }

	  }
}
